import {
  getLyric,
  getPlaylistDetail,
  getPlaylistSubscribe,
  getPlaylistTrackAll,
  getSongDetail,
  getSongUrl,
  getRecommendSongs
} from "@/api/home";
import {getUserFollows} from "@/api/share/index"
import {getSongDownloadUrl} from "@/api/login/index"

import saveAs from 'file-saver'
import {asString, parseLyric} from "@/utils/index"
import _ from 'lodash'
import {toRaw} from "vue";

import {Notify} from "vant";
import {getAlbum, getArtistAlbum} from "@/api/album/index";
import {getUserFolloweds} from "../../api/share/index.js";

const dataMusic = {
  privilegesTracks: [], // 歌单集合
  playlistInfo: [], // 歌曲信息集合
  songUrlIndex: 0, // 歌曲下标进行持久化存储
  lyric: null, // 歌词
  playerTime: 0, // 当前播放的歌词位置
  musicId: '', // 添加一首歌曲或者多首歌曲到我的歌单的id
  // 音频控件数据
  audioOptions: {
    volume: 1, // 音量大小
    isVolume: false, // 是否显示音量控件
    isPaused: true, // 是否暂停 默认暂停 为了切换播放暂停icon
    totalPlayTime: '00:00', // 总播放時間
    currentlyPlaying: '00:00', // 当前播放时间
    setProgressBarStatus: true, // 设置进度条状态，当拖动时不允许重新赋值，直到停止拖动
    progressBarMax: 0, // 设置进度条最大长度，跟随音频时间来
    playProgressBar: 0, // 播放时进度条需要走动
    currentTime: 0 // 记录当前播放时间
  },
  collect: [], // 临时存储当前歌单是否收藏
  playerInstance: null, // 播放器实例
  noPlayerControl: false, // 移动端音乐详情不显示底部播放控件
  listPlaylistDetails: {}, // 点击歌单获取当前歌单的信息用来展示信息
  paginationPlaylist: [], // 歌单中的歌曲分页数据
  fan: [], // 粉丝
}
const playMusicGather = {
  // TODO: 多增加一个字段用来判断是向播放列表中新增还是替换（已解决）
  // 获取歌曲列表的信息，用来播放的 flag用来判断是否追加歌单还是切换歌单false: 切换 true追加
  getPlaylistDetail(id, flag = false) {
    getPlaylistDetail(id).then(async (res) => {
      const {code, playlist} = res
      if (Number(code) === 200) {
        // 判断是追加歌单还是播放歌单
        await this.setDetachment(playlist.tracks, flag)
      }
    })
  },
  // 获取歌曲播放信息，这个是获取歌单的信息
  getSongUrl() {
    // 如果保存的歌单有数据，就请求数据
    if (this.privilegesTracks.length > 0)
        // id可以是多个id: '111,22,33' asString作用将数组转为字符串并用逗号分割
      return getSongUrl(asString(this.privilegesTracks)).then((res) => {
        // console.log(res)
        const {code, data} = res
        if (Number(code) === 200) {
          let newPlistInfo = [] // 播放器需要的字段
          let objType = {}
          // 获取歌单集合，有些内容歌曲数据中没有需要从歌单中获取
          const tracks = this.privilegesTracks
          tracks.map((track, trackIndex) => {
            data.forEach((item) => {
              // 将这些数据存到数组中，最后存储到本地存储
              // 由于传递多个id返回的数据不是按顺序返回的所以需要处理
              if (track.id === item.id && !(track[trackIndex]?.mainSong)) {
                objType = {
                  src: item.url, // 原数据item.url `https://music.163.com/song/media/outer/url?id=${item.id}.mp3`
                  id: item.id, // 歌曲id
                  al: tracks[trackIndex].al, // 歌曲信息
                  ar: tracks[trackIndex].ar, // 歌手信息
                  name: tracks[trackIndex].name, // 歌曲名称
                  dt: tracks[trackIndex].dt // 歌曲时间
                }
                // 将objType播放器需要的字段push到数组中
                newPlistInfo.push(objType)
                // 保存电台播放数据
              } else if (track.mainSong?.id === item.id) {
                objType = {
                  src: item.url, // 原数据item.url `https://music.163.com/song/media/outer/url?id=${item.id}.mp3`
                  id: item.id, // 歌曲id
                  al: tracks[trackIndex].mainSong.album, // 歌曲信息
                  ar: tracks[trackIndex].mainSong.artists, // 歌手信息
                  name: tracks[trackIndex].mainSong.name, // 歌曲名称
                  dt: tracks[trackIndex].mainSong.bMusic.playTime, // 歌曲时间
                  noLyric: true // 电台不请求歌词
                }
                // console.log(tracks[trackIndex].mainSong)
                newPlistInfo.push(objType)
              }
            })
          })

          // 将处理过的数据赋值给playlistInfo方便getters和watchEffect监听数据
          this.playlistInfo = newPlistInfo
          return newPlistInfo
        }
      })
    // ，没有数据就返回空
    return new Promise(resolve => {
      resolve([])
    })
  },
  // 歌曲详情将一条数据添加到播放列表中 TODO:已解决
  // flag用来判断是否追加歌单还是播放当前歌曲 false 是播放歌曲，true追加歌曲
  getSongDetail(id, flag = false) {
    getSongDetail(id).then(async res => {
      const {code, songs} = res
      // console.log(res)
      if (Number(code) === 200) {
        if (songs.length === 0) {
          Notify({
            message: '无法播放全部歌曲',
            background: '#ff0000',
            color: '#ffffff'
          })
          return
        }
        let songUrl = await this.addSongUrl(songs[0].id)
        const objType = {
          // TODO: 由于获取音乐播放地址会出现403的情况所以通过下方这个形式解决(这种方式解决容易产生跨域)（未解决）
          // https://music.163.com/song/media/outer/url?id=id.mp3, 原数据：songUrl.url `https://music.163.com/song/media/outer/url?id=${songUrl.id}.mp3`
          src: songUrl.url,
          id: songUrl.id, // 歌曲id
          al: songs[0].al, // 歌曲信息
          ar: songs[0].ar, // 歌手信息
          name: songs[0].name, // 歌曲名称
          dt: songs[0].dt // 歌曲时间
        }
        if (!flag) {
          // 播放歌曲
          // 使用lodash库进行数组去重第一个是数组，第二个是，根据id进行比对
          // 歌曲列表，将数据重新存储
          this.privilegesTracks = _.uniqBy([...songs, ...toRaw(this.privilegesTracks)], 'id')
          // 使用lodash库进行数组去重第一个是数组，第二个是，根据id进行比对  存储的是播放的数据
          this.playlistInfo = _.uniqBy([objType, ...this.playlistInfo], 'id')

          // 每次添加单首歌曲需要将播放歌曲下标重置为0
          this.songUrlIndex = 0
          // 添加播放新歌，播放时间也重置
          this.audioOptions.currentTime = 0
        } else {
          // 追加歌曲到本地存储
          // 使用lodash库进行数组去重第一个是数组，第二个是，根据id进行比对
          // 歌曲列表，将数据重新存储
          this.privilegesTracks.push(...songs)
          this.privilegesTracks = _.uniqBy([...toRaw(this.privilegesTracks)], 'id')
          // 追加到播放列表
          this.playlistInfo.push(objType)
          // 使用lodash库进行数组去重第一个是数组，第二个是，根据id进行比对  存储的是播放的数据
          this.playlistInfo = _.uniqBy([...this.playlistInfo], 'id')
        }
        // console.log(this.playlistInfo)
      }
    })
  },
  // 添加一首歌曲数据到列表中，作用就是用来添加歌曲播放信息
  addSongUrl(id) {
    return getSongUrl(id).then(res => {
      const {code, data} = res
      if (Number(code) === 200) {
        return data[0]
      }
    })
  },
  // 从集合中删除一首歌或者清空，要删除两个地方privilegesTracks和playlistInfo中的
  removeSongUrl(id = '', index = '') {

    // id存在就删除一首，否则清空
    if (id) {
      // 会改变原数组，这个是清除歌单的数据
      _.remove(this.privilegesTracks, (n) => {
        if (n?.mainSong) {
          return n.mainSong.id === id
        } else {
          return n.id === id
        }
      })
      // 清除歌曲数据
      _.remove(this.playlistInfo, (n) => {
        return n.id === id
      })
      // 如果删除的歌曲小于本地存储播放的歌曲下标，那就让本地存储播放的歌曲下标减一
      if (index < this.songUrlIndex) {
        this.songUrlIndex -= 1
      } else if (index === this.songUrlIndex) { // 如果删除的正好是当前播放的歌曲就让播放时间重置
        // 清空播放时间也重置
        this.audioOptions.currentTime = 0
      }
    } else {
      // 清空所有的
      this.privilegesTracks.splice(0, this.privilegesTracks.length)
      this.playlistInfo.splice(0, this.playlistInfo.length)
      this.playerInstance.playingNull()
      // 清空需要将播放歌曲下标重置为0
      this.songUrlIndex = 0
      // 清空播放时间也重置
      this.audioOptions.currentTime = 0
    }
  },
  // 获取歌词，flag === true是获取滚动歌词，否则获取的是歌曲详情的歌词
  getLyric(id, flag = false) {
    return getLyric(id).then(res => {
      // console.log(res)
      const {code, lrc} = res
      if (Number(code) === 200) {
        // parseLyrics解析歌词，key是歌词时间戳
        let saveLyric = parseLyric(lrc.lyric)
        if (flag) {
          let htmlLyric = ''
          // 将返回的歌词进行处理
          saveLyric.forEach(item => {
            htmlLyric += item.lyric + '<br />'
          })
          return htmlLyric
        } else {
          this.lyric = saveLyric
        }
      }
    })
  },
  // 下载音乐
  getSongDownloadUrl({id, musicName, singerName}) {
    getSongDownloadUrl({id}).then(async res => {
      const {code, data} = res
      // console.log(res)
      if (Number(code) === 200 && data.encodeType) {
        Notify({
          message: '下载中',
          background: '#ffe1e1',
          color: '#ad0000'
        })
        // 参数第一个是音乐地址，后面是音乐名称，歌手名称，后缀
        await saveAs.saveAs(data.url, `${musicName}-${singerName}.${data.encodeType}`)
      } else {
        Notify({
          message: '无法下载，可能是未登录、或者歌曲不支持下载',
          background: '#ff0000',
          color: '#ffffff'
        })
      }
    })
  },
  // 点击卡片获取歌单详情
  clickGetPlaylistDetail(id) {
    getPlaylistDetail(id).then((res) => {
      const {code, playlist} = res
      if (Number(code) === 200) {
        this.listPlaylistDetails = playlist // 歌单信息 包括歌信息
        // console.log(this.listPlaylistDetails)
        // 获取歌曲
        this.getPlaylistTrackAll()
        /**
         *@params：
         *@desc：下面是新接口
         *@author：羽
         *@date 2022/08/13 15:42:54
         */
        // 获取评论 获取评论根据type来判断是哪种歌曲 { id: '', pageSize: 20每页数据, type: 2 歌单, pageNo: 1第几页, sortType: 3按时间排序, cursor: 上一页最后一条数据的time 1660365874079 }
        // this.getCommentNew()
      }
    })
  },
  // params{ uid: id, limit: 30, offset: 1 } 我所关注的
  getUserFollows(params) {
    // 判断是传递的
    if (!params) {
      // 在用户信息存在的情况下才获取关注
      if (this.userInfo.userId)
        getUserFollows({uid: this.userInfo.userId}).then(res => {
          const {code, follow} = res
          if (Number(code) === 200) {
            this.fan = follow
          }
        })
    } else {
      const {userId, num, limit} = params
      return getUserFollows({uid: userId, limit, offset: (num - 1) * limit}).then(res => {
        const {code, follow} = res
        if (Number(code) === 200) {
          return follow
        }
      })
    }
  },
  // params{ uid: id, limit: 30, offset: 1 } 我的粉丝
  getUserFolloweds(params) {
    const {userId, num, limit} = params
    return getUserFolloweds({uid: userId, limit, offset: (num - 1) * limit}).then(res => {
      const { followeds, code } = res
      if (Number(code) === 200) return followeds
    })
  },
  // 收藏歌单
  getPlaylistSubscribe(id) {
    // t : 类型,1:收藏,2:取消收藏 id : 歌单 id
    getPlaylistSubscribe({id, t: 1}).then(res => {
      if (Number(res.code) === 200) {
        // 将当前点击存储的歌单id临时存储
        this.collect.push(id)
        Notify({
          message: '收藏成功',
          background: '#ffe1e1',
          color: '#ad0000'
        })
      }
    })
  },
  // params = { id: '', limit: 10, offset: 0}, 获取歌单歌曲通过num控制偏移量和返回数量
  getPlaylistTrackAll(num = 1) {
    getPlaylistTrackAll({id: this.listPlaylistDetails.id, limit: 20, offset: (num - 1) * 20}).then(res => {
      const {code, songs} = res
      if (Number(code) === 200) {
        this.paginationPlaylist = songs
      }
      // console.log(res)
    })
  },
  // 点击单纯获取歌曲详情
  getOnlySongDetail(ids) {
    return getSongDetail(ids).then(res => {
      if (Number(res.code) === 200)
        return res
    })
  },
  // 获取专辑详情用来渲染页面
  getAlbum(id) {
    return getAlbum(id).then(res => {
      if (Number(res.code) === 200) {
        // console.log(res)
        return res
      }
    })
  },
  // 用于添加到播放列表中和播放当前专辑
  getAlbumPlayer(id, flag = false) {
    getAlbum(id).then(async res => {
      const {code, songs} = res
      if (Number(code) === 200) {
        if (flag) {
          // 追加播放歌单，uniqBy用来去重
          this.privilegesTracks = _.uniqBy([...toRaw(this.privilegesTracks), ...songs], 'id')
          // 获取歌曲信息
          await this.getSongUrl()
        } else {
          // 存储歌单 tracks中的al歌曲信息，ar歌手信息
          this.privilegesTracks = songs
          // 获取歌曲信息
          await this.getSongUrl()
          // 播放下标重置
          this.songUrlIndex = 0
          // 切换播放歌单，播放时间也重置
          this.audioOptions.currentTime = 0
        }
      }
    })
  },
  // 获取歌手其他专辑 { id:歌手id, limit: 返回数据, offset: 偏移量 }
  getArtistAlbum(params) {
    return getArtistAlbum(params).then(res => {
      if (Number(res.code) === 200) {
        return res
      }
      // console.log(res)
    })
  },
  // 将每日歌曲的数据添加到播放列表或者播放每日歌曲的数据
  // flag用来判断是播放还是追加歌曲
  getRecommendSongs(flag = false) {
    getRecommendSongs().then(async res => {
      if (Number(res.code) === 200) {
        // 用来判断是追加歌单还是播放歌单
        await this.setDetachment(res.data.dailySongs, flag)
      }
    })
  },
  // 用来抽离，追加播放还是直接播放
  async setDetachment(musicLis, flag) {
    if (flag) {
      // 追加
      // 追加播放歌单，uniqBy用来去重
      this.privilegesTracks = _.uniqBy([...toRaw(this.privilegesTracks), ...musicLis], 'id')
      await this.getSongUrl()
    } else {
      // 播放
      // 存储歌单 tracks中的al歌曲信息，ar歌手信息
      this.privilegesTracks = musicLis
      // // 切换歌集的时候重置歌曲下标 TODO:切换歌单的时候需要重置下标（已解决）
      await this.getSongUrl()
      this.songUrlIndex = 0
      // 切换播放歌单，播放时间也重置
      this.audioOptions.currentTime = 0
    }
  }
}
const getterMusic = {
  // 监听歌曲信息，返回的是已经解析的数据可以播放的
  playlistInfoFn() {
    getSongUrl(asString(this.privilegesTracks))
    return this.playlistInfo
  }
}

export {
  dataMusic,
  playMusicGather,
  getterMusic
}
